#include "stdafx.h"
#include "Predator.hpp"
#include "Simulation.hpp"
#include "ArtificialSea.h"
#include <boost/lexical_cast.hpp>

int Predator::_id = 0;

//////////////////////////////////////////////////////////////////////////

Predator::Predator(const vec3& pos)
	: Agent(pos), _animationState(0), _model(0)
{
	Ogre::SceneManager* sm = ArtificialSea::getSingleton().getSceneManager();
	Ogre::String name = "Predator" + boost::lexical_cast<Ogre::String>(_id++);
	_sceneNode = sm->getRootSceneNode()->createChildSceneNode(_position);
	_model = sm->createEntity(name, "shark.mesh");
	_sceneNode->attachObject(_model);
	//_axesNode = sm->getRootSceneNode()->createChildSceneNode(_position);
	//_axesNode->attachObject(sm->createEntity(name+"2", "axes.mesh"));
	_sceneNode->resetOrientation();
	_sceneNode->setDirection(_headingSmoothed, Ogre::SceneNode::TS_WORLD);
	_sceneNode->setScale(0.3f, 0.3f, 0.3f);
	_animationState = _model->getAnimationState("swim");
	_animationState->setEnabled(true);
	_animationState->setLoop(true);
}

Predator::~Predator()
{
	_sceneNode->removeAndDestroyAllChildren();
	//_axesNode->removeAndDestroyAllChildren();
	ArtificialSea::getSingleton().getSceneManager()->destroySceneNode(_sceneNode);
	//ArtificialSea::getSingleton().getSceneManager()->destroySceneNode(_axesNode);
}

//////////////////////////////////////////////////////////////////////////

vec3 Predator::calcSteeringForce(float dt)
{
	vec3 force = vec3::ZERO;

	if (Simulation::Get().tagNeighborAgents(*this, PM.predator.pursuit.attackRadius->getRealValue(), AGENT_FISH) > 0)
	{
		force += _steering.pursuit(this, PM.predator.maxVelocity->getRealValue(), PM.predator.pursuit.timeScale->getRealValue());
	}
	else
	{
		force += _steering.wander(
			this, dt, PM.predator.wander.jitter->getRealValue(), PM.predator.wander.radius->getRealValue(), PM.predator.wander.distance->getRealValue());
	}

	if (Simulation::Get().tagNeighborAgents(*this, 40.0f, AGENT_PREDATOR) > 0)
	{
		vec3 evadePredForce = _steering.evade(this, PM.predator.maxVelocity->getRealValue(), 0, 1.0f);
		force = (force + evadePredForce.normalisedCopy() * force.length()) / 2;
	}

	force = force.normalisedCopy() * PM.forceScale->getRealValue();
	return force;
}

//////////////////////////////////////////////////////////////////////////

void Predator::draw() const
{
	//static const float WIDTH = 12.0f;
	//static const float LENGTH = 20.0f;

	//vec2 center(_position.x, _position.y);
	////vec2 heading(_heading.x, _heading.y);
	//vec2 heading(_headingSmoothed.x, _headingSmoothed.y);
	//vec2 side = heading.perpendicular();

	//vec2 baseA = center - side * (WIDTH*0.5f) - heading * (LENGTH*0.5f);
	//vec2 baseB = center + side * (WIDTH*0.5f) - heading * (LENGTH*0.5f);
	//vec2 front = center + heading * (LENGTH*0.5f);

	//VideoDriver::Get().DrawFilledTriangle(
	//	front.x, front.y, baseA.x, baseA.y, baseB.x, baseB.y, Colors::CadetBlue);
	//VideoDriver::Get().DrawHollowTriangle(
	//	front.x, front.y, baseA.x, baseA.y, baseB.x, baseB.y, 2, Colors::DarkBlue);
}

//////////////////////////////////////////////////////////////////////////

void Predator::update(float dt)
{
	Agent::update(dt);

	_animationState->addTime(dt);

	vec3 zAxis = -_headingSmoothed;
	vec3 xAxis = -zAxis.crossProduct(vec3(0,1,0)).normalisedCopy();
	vec3 yAxis = zAxis.crossProduct(xAxis).normalisedCopy();

	_sceneNode->resetOrientation();
	_sceneNode->setPosition(_position);
	_sceneNode->setOrientation(quat(xAxis, yAxis, zAxis));

	//_axesNode->resetOrientation();
	//_axesNode->setPosition(_position);
	////_axesNode->setDirection(_headingSmoothed, Ogre::SceneNode::TS_WORLD, vec3::NEGATIVE_UNIT_Z);
	//_axesNode->setOrientation(quat(xAxis, yAxis, zAxis));
	
	//float roll = -_sceneNode->getOrientation().getRoll().valueRadians();
	////if (fabsf(roll) > dt) roll = roll / fabsf(roll) * dt;

	//_sceneNode->roll(Ogre::Radian(roll), Ogre::Node::TS_LOCAL);
	//_axesNode->roll(Ogre::Radian(roll), Ogre::Node::TS_LOCAL);

	//vec3 xVec(-_headingSmoothed);
	//vec3 zVec = xVec.crossProduct(vec3(0,1,0));
	//vec3 yVec = xVec.crossProduct(zVec);
	//quat orient(xVec, yVec, zVec);
	//_sceneNode->resetOrientation();
	//_sceneNode->setOrientation(orient);

	//vec3 localY = _sceneNode->getOrientation() * vec3::UNIT_Y;
	//quat q = localY.getRotationTo(vec3::UNIT_Y);
	//_sceneNode->rotate(q, Ogre::Node::TS_WORLD);
}

//////////////////////////////////////////////////////////////////////////